<template>
  <div
    ref="editorContainer"
    class="editor-container"
    :style="editorStyle"
  ></div>
  <div v-if="!unref(instanceOptions).hideParameters">
    <div class="tooltip">{{ tooltip }}</div>
    <div class="queryList">
      <Row>
        <Col :span="4">
          <Button type="link" @click="onAdd">添加参数</Button>
        </Col>
        <Col :span="20">
          <Row v-for="item in sqlStr" :key="item.id">
            <Col :span="7">
              <div class="item">
                <div class="label">参数名</div>
                <Input placeholder="非必填" v-model:value="item.label" />
              </div>
            </Col>
            <Col :span="7">
              <div class="item">
                <div class="label">参数值</div>
                <Input placeholder="非必填" v-model:value="item.insertText" />
              </div>
            </Col>
            <Col :span="7">
              <div class="item">
                <div class="label">描述</div>
                <Input placeholder="非必填" v-model:value="item.detail" />
              </div>
            </Col>
            <Col :span="3">
              <Button
                type="link"
                :icon="h(CloseOutlined)"
                @click="onDelete"
              ></Button>
            </Col>
          </Row>
        </Col>
      </Row>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  computed,
  defineEmits,
  defineProps,
  h,
  onBeforeUnmount,
  onMounted,
  ref,
  unref,
  watch,
} from 'vue';
import { CloseOutlined } from '@ant-design/icons-vue';
import loader from '@monaco-editor/loader';
import { Button, Col, Input, Row } from 'ant-design-vue';

const onAdd = () => {
  sqlStr.value.push({
    id: sqlStr.value.length + 1,
    label: '',
    insertText: '',
    detail: '',
  });
};
const sqlList = computed(() => {
  const list = sqlStr.value.map((i) => {
    return {
      ...i,
      label: `_${i.label}`,
      insertText: '${{' + i.insertText + '}}',
    };
  });
  console.log(list, 'list');

  return list;
});
const onDelete = (item) => {
  const index = sqlStr.value.findIndex((i) => i.id === item.id);
  sqlStr.value.splice(index, 1);
};
const props = defineProps({
  value: String,
  language: {
    type: String,
    default: 'shell',
  },
  theme: {
    type: String,
    default: 'vs-dark',
  },
  option: {
    type: Object,
    default: () => {},
  },
});
const defaultOptions = {
  hideParameters: false,
  editorHeight: '40vh',
};

const instanceOptions = computed(() => {
  const { option } = props;
  const currentOptions = {
    ...defaultOptions,
    ...option,
  };
  return currentOptions;
});

const tooltip = '使用 @{{ xxx }} 来替换参数, 输入_可以获取全部变量';
const emits = defineEmits(['update:value']);
const sqlStr = ref([]);
const editorContainer = ref(null);
let editorInstance = null;

onMounted(() => {
  loader.init().then((monaco) => {
    editorInstance = monaco.editor.create(editorContainer.value, {
      value: props.value || '',
      language: props.language,
      theme: props.theme,
    });

    editorInstance.onDidChangeModelContent(() => {
      emits('update:value', editorInstance.getValue());
    });

    monaco.languages.registerCompletionItemProvider('shell', {
      provideCompletionItems: function (model, position) {
        // 获取当前行数
        const line = position.lineNumber;

        // 获取当前列数
        const column = position.column;
        // 获取当前输入行的所有内容
        const content = model.getLineContent(line);
        // 通过下标来获取当前光标后一个内容，即为刚输入的内容
        const sym = content[column - 2];
        const word = model.getWordUntilPosition(position);
        const range = {
          startLineNumber: position.lineNumber,
          endLineNumber: position.lineNumber,
          startColumn: word.startColumn,
          endColumn: word.endColumn,
        };
        const suggestions = [];
        if (sym === '_') {
          for (const i in sqlList.value) {
            suggestions.push({
              label: sqlList.value[i].label, // 显示的提示内容
              kind: monaco.languages.CompletionItemKind['Function'], // 用来显示提示内容后的不同的图标
              insertText: sqlList.value[i].insertText, // 选择后粘贴到编辑器中的文字
              detail: sqlList.value[i].detail, // 提示内容后的说明
              range: range,
            });
          }
        }
        return {
          suggestions: suggestions,
        };
      },
      triggerCharacters: ['$', ''],
    });
  });
});

onBeforeUnmount(() => {
  if (editorInstance) {
    editorInstance.dispose();
  }
});

watch(
  () => props.language,
  (newLanguage) => {
    if (editorInstance) {
      loader.init().then((monaco) => {
        monaco.editor.setModelLanguage(editorInstance.getModel(), newLanguage);
      });
    }
  },
);

watch(
  () => props.value,
  (newValue) => {
    if (editorInstance && editorInstance.getValue() !== newValue) {
      editorInstance.setValue(newValue);
    }
  },
);

const editorStyle = computed(() => {
  return {
    height: unref(instanceOptions).editorHeight,
  };
});
</script>

<style lang="scss" scoped>
.editor-container {
  width: 100%;
  height: 40vh;
}
.tooltip {
  margin: 10px 0;
  font-size: 12px;
}
.queryList {
  .item {
    display: flex;
    align-items: center;
    margin-bottom: 15px;
    .label {
      white-space: nowrap;
      margin: 0 15px;
    }
  }
}
</style>
